home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume91 / utilitys / ed3_1_1 / part06 / edvan.c
C/C++ Source or Header  |  1991-11-07  |  32KB  |  1,474 lines

  1. /*
  2.     These are miscellaneous vanilla functions of ed3,
  3.         using no graphics or intuition calls.
  4.  
  5. 10-22-91 chg YZ to ZY
  6.          fixed a very small (but serious) bug in find_dual
  7. 10-13-91 added fibo() fibonacci (?) function
  8.          stellate() now checks to see if there is room in the undo buf
  9. 09-25-91 chg points_are_a_face2 to face_next_to_edge
  10.          add adjacent_fp(), adjacent_pp(), adjacent_xx()
  11.          fix a problem in find_dual with polys->polys
  12. 09-06-91 adapted to use coord instead of short
  13.          rem distance_between_points
  14. 09-04-91 chg face_next_to_edge() to allow an ignored face
  15. 09-03-91 chg rotate() to support the rotate_all flag
  16.          implement deselect_connected()
  17. 09-02-91 add center_to_origin(), move_point_rel(), move_point_to()
  18. 08-27-91 add points_are_on_a_poly()
  19. 08-26-91 fix to point_is_on_a_face()
  20.          add point_is_on_a_poly()
  21. 08-24-91 add stellate() (hey, it was easy!)
  22.          add glue_points()    (also easy)
  23. 08-23-91 added refresh_all(), toggle_dtool()
  24. 08-21-91 added select_all(), select_connected(), deselect_all(),
  25.          deselect_connected(), toggle_select();
  26. 08-15-91 added find_center()
  27.          added find_radius()
  28.          chg find_dual to support assume_poly flag
  29. */
  30.  
  31. #include "sysnogr.h"
  32.  
  33.  
  34. #if INTEGER
  35. void center_to_origin()
  36. {
  37.     double dcx, dcy, dcz;
  38.     pixel cx, cy, cz;
  39.     index p;
  40.  
  41.     if (!points) return;
  42.  
  43.     find_center(&dcx, &dcy, &dcz);
  44.     cx = dcx;
  45.     cy = dcy;
  46.     cz = dcz;
  47.  
  48.     if (!cx && !cy && !cz)
  49.     {
  50.         screen_say("Points are already centered");
  51.         return;    /* already at center */
  52.     }
  53.  
  54.     for (p = 0; p < points; p++)
  55.       move_point_rel(p, -cx, -cy, -cz);
  56.  
  57.     refresh_all();
  58. }
  59. #else
  60. void center_to_origin()
  61. {
  62.     double dcx, dcy, dcz;
  63.     index p;
  64.  
  65.     if (!points) return;
  66.  
  67.     find_center(&dcx, &dcy, &dcz);
  68.  
  69.     if ((dcx > -.001 && dcx < .001) &&
  70.         (dcy > -.001 && dcy < .001) &&
  71.         (dcz > -.001 && dcz < .001))
  72.     {
  73.         screen_say("Points are already centered");
  74.         return;    /* already at center */
  75.     }
  76.  
  77.     for (p = 0; p < points; p++)
  78.       move_point_rel(p, -dcx, -dcy, -dcz);
  79.  
  80.     refresh_all();
  81. }
  82. #endif
  83.  
  84.  
  85. void reset_zoom()
  86. {
  87.   SCALE = 1.0;
  88.   offset.x = offset.y = offset.z = 0;
  89. }
  90.  
  91.  
  92. void move_point_rel(p, dx, dy, dz)
  93. index p;
  94. coord dx, dy, dz;
  95. {
  96.     action_move_p(p, dx, dy, dz);
  97.  
  98.     point[p].x += dx;
  99.     point[p].y += dy;
  100.     point[p].z += dz;
  101.     convert_point(p);
  102. }
  103.  
  104.  
  105. void move_point_to(p, x, y, z)
  106. index p;
  107. coord x, y, z;
  108. {
  109.     action_move_p(p, x-point[p].x, y-point[p].y, z-point[p].z);
  110.  
  111.     point[p].x = x;
  112.     point[p].y = y;
  113.     point[p].z = z;
  114.     convert_point(p);
  115. }
  116.  
  117.  
  118. void refresh_all()
  119. {
  120.     int i1;
  121.  
  122.     draw_faces(1);
  123.     draw_points(0);
  124.     if (flags.display_dtool)
  125.         draw_distance_tool();
  126.     if (flags.show_coords) draw_coords(0);
  127.     if (mode == M_MORE || mode == M_KMORE)
  128.         redraw_newface();    /* redraw the partially completed face */
  129.     if (mode == M_MORE)
  130.     {
  131.         if (flags.shape == M_FACE)
  132.             for (i1 = 0; i1 < new_seg; i1++) tri_up_point(face[faces].p[i1]);
  133.         else
  134.             for (i1 = 0; i1 < new_seg; i1++) tri_up_point(temp_poly[i1]);
  135.     }
  136.     if (mode == M_KMORE)
  137.     {
  138.         if (flags.shape == M_FACE)
  139.             for (i1 = 0; i1 < new_seg; i1++) tri_down_point(face[faces].p[i1]);
  140.         else
  141.             for (i1 = 0; i1 < new_seg; i1++) tri_down_point(temp_poly[i1]);
  142.     }
  143.     if (flags.crosshair) draw_hair();            /* Erase/Redraw crosshair */
  144.     draw_bars();
  145.     show_counts();
  146. }
  147.  
  148.  
  149. void toggle_dtool()
  150. {
  151.     flags.display_dtool ^= 1;
  152.     draw_distance_tool();
  153.     /* if we turn the dtool off, exit dtool mode */
  154.     if (!flags.display_dtool && mode == M_DIST)
  155.     {
  156.         mode = M_ADDP;
  157.         draw_bars();
  158.     }
  159. }
  160.  
  161.  
  162. void select_all()
  163. {
  164.     index p, limit;
  165.  
  166.     deselect_all();
  167.  
  168.     limit = (points >= MAX_SELECT ? MAX_SELECT : points);
  169.     for (p = 0; p < limit; p++)
  170.     {
  171.         select_p[p] = p;
  172.         box_point(p);                /* select it visually */
  173.         point[p].code |= PF_SELECTED;    /* set selected flag */
  174.     }
  175.     selected = p;
  176. }
  177.  
  178.  
  179. void deselect_all()
  180. {
  181.     index i1;
  182.  
  183.     for (i1 = 0; i1 < selected; i1++)
  184.     {
  185.         point[select_p[i1]].code &= ~PF_SELECTED;    /* turn off selected flag */
  186.         box_point(select_p[i1]);                    /* and deselect it visually */
  187.     }
  188.     selected = 0;
  189. }
  190.  
  191.  
  192. /*
  193.     If the starting point is specified, the search limits itself to points
  194.     connected to the starting point.  Otherwise, the search starts from
  195.     every selected point
  196. */
  197.  
  198. void select_connected(starting_point)
  199. index starting_point;
  200. {
  201.     int sp, i1, i2, i3, verts;    /* selected point, face and polygon indices */
  202.     index start_p, p;
  203.     index orig_selected = selected;
  204.  
  205.     start_p = 0;
  206.  
  207.     if (starting_point >= 0)
  208.     {
  209.         for (i1 = 0; i1 < selected; i1++)
  210.             if (starting_point == select_p[i1])
  211.             {
  212.                 start_p = i1;
  213.                 break;
  214.             }
  215.     }
  216.  
  217.     for (sp = start_p; sp < selected; sp++)
  218.     {
  219.         p = select_p[sp];
  220.  
  221.         for (i1 = 0; i1 < faces; i1++)
  222.         for (i2 = 0; i2 < 3; i2++)
  223.             if (face[i1].p[i2] == p)
  224.             {
  225.                 /* select the other points of this face */
  226.                 select_point(face[i1].p[(i2+1)%3]);
  227.                 select_point(face[i1].p[(i2+2)%3]);
  228.             }
  229.  
  230.         for (i1 = 0; i1 < polys; i1++)
  231.         {
  232.             verts = poly[i1].verts;
  233.             for (i2 = 0; i2 < verts; i2++)
  234.             {
  235.                 if (poly[i1].p[i2] == p)
  236.                 {
  237.                     /* select the other points of this poly */
  238.                     for (i3 = 1; i3 < verts; i3++)
  239.                     select_point(poly[i1].p[(i2 + i3) % verts]);
  240.                 }
  241.             }
  242.         }
  243.  
  244.         if (starting_point >= 0 && sp == start_p)
  245.             sp = orig_selected-1;
  246.     }
  247. }
  248.  
  249.  
  250. #define DS_MAX 500
  251. index dselect[DS_MAX];
  252. index dselected;
  253.  
  254. void deselect_connected(starting_point)
  255. index starting_point;
  256. {
  257.     int i1, i2, i3, verts;    /* selected point, face and polygon indices */
  258.     index dp, p, newp;
  259.  
  260.     dselected = 1;
  261.     dselect[0] = starting_point;
  262.  
  263.     for (dp = 0; dp < dselected; dp++)
  264.     {
  265.         p = dselect[dp];
  266.  
  267.         for (i1 = 0; i1 < faces; i1++)
  268.         for (i2 = 0; i2 < 3; i2++)
  269.         if (face[i1].p[i2] == p)
  270.         {
  271.             /* deselect the other points of this face */
  272.             newp = face[i1].p[(i2+1)%3];
  273.             if (pselected(newp))
  274.             {
  275.                 deselect_point(newp);
  276.                 dselect[dselected++] = newp;
  277.                 if (dselected == DS_MAX) return;
  278.             }
  279.  
  280.             newp = face[i1].p[(i2+2)%3];
  281.             if (pselected(newp))
  282.             {
  283.                 deselect_point(newp);
  284.                 dselect[dselected++] = newp;
  285.                 if (dselected == DS_MAX) return;
  286.             }
  287.         }
  288.  
  289.         for (i1 = 0; i1 < polys; i1++)
  290.         {
  291.             verts = poly[i1].verts;
  292.             for (i2 = 0; i2 < verts; i2++)
  293.             if (poly[i1].p[i2] == p)
  294.             for (i3 = 1; i3 < verts; i3++)    /* select the other points of this poly */
  295.             {
  296.                 newp = poly[i1].p[(i2 + i3) % verts];
  297.                 if (pselected(newp))
  298.                 {
  299.                     deselect_point(newp);
  300.                     dselect[dselected++] = newp;
  301.                     if (dselected == DS_MAX) return;
  302.                 }
  303.             }
  304.         }
  305.     }
  306. }
  307.  
  308.  
  309. void toggle_select(buttons, tp)
  310. int buttons;
  311. index tp;
  312. {
  313.     if (buttons & 2)    /* double click: select connected */
  314.     {
  315.         if (pselected(tp))
  316.             select_connected(tp);
  317.         else
  318.             deselect_connected(tp);
  319.     }
  320.     else        /* toggle individual point */
  321.     {
  322.         if (pselected(tp))
  323.             deselect_point(tp);
  324.         else
  325.             select_point(tp);
  326.     }
  327. }
  328.  
  329.  
  330. void glue(nearest)
  331. index nearest;
  332. {
  333.     index second;
  334.  
  335.     if (nearest < 0) return;    /* must have valid point */
  336.     second = find_nearest_in_space(point[nearest].x, point[nearest].y,
  337.             point[nearest].z, nearest);
  338.     if (second < 0) return;
  339.     begin_operation();
  340.     glue_points(nearest, second);
  341.     end_operation();
  342.     refresh_all();
  343. }
  344.  
  345.  
  346. /*
  347.     glue_points fuses two points together into one point.
  348.     They should be spatially close to begin with.
  349. */
  350.  
  351. void glue_points(p0, p1)
  352. {
  353.     Point3D new;    /* coordinate of new fused point */
  354.     index i1, vert;
  355.     index changed[MAX_EDGES];
  356.     index found = 0;
  357.     index f, q;
  358.     index fp0, fp1, fp2;
  359.  
  360.     new.x = (point[p0].x + point[p1].x)/2;
  361.     new.y = (point[p0].y + point[p1].y)/2;
  362.     new.z = (point[p0].z + point[p1].z)/2;
  363.  
  364.     /* handle possible degenerations of faces and polys */
  365.     for (f = 0; f < faces; f++)        /* search all faces */
  366.     {
  367.         fp0 = face[f].p[0];
  368.         fp1 = face[f].p[1];
  369.         fp2 = face[f].p[2];
  370.  
  371.         if ((fp0 == p0 && fp1 == p1) ||
  372.             (fp1 == p0 && fp0 == p1) ||
  373.             (fp0 == p0 && fp2 == p1) ||
  374.             (fp2 == p0 && fp0 == p1) ||
  375.             (fp1 == p0 && fp2 == p1) ||
  376.             (fp2 == p0 && fp1 == p1))
  377.         {
  378.             del_face(f, 0);    /* faces cannot degenerate into lines */
  379.             f--;    /* don't skip a face */
  380.         }
  381.     }
  382.     /* now look for a polygon having these two points as an edge */
  383.     /* yeah, calling a function here makes things slower, but hey, speed is
  384.         probably not important.  If it was, we could use our own loop here. */
  385.     while ((q = poly_next_to_edge(p0, p1, -1)) != -1)
  386.     {
  387.         /* which vertex is it? */
  388.         for (vert = 0; vert < poly[q].verts; vert++)
  389.             if (poly[q].p[vert] == p1)
  390.             {
  391.                 delete_vertex(q, vert, 0);
  392.                 break;    /* breaks out of for loop */
  393.             }
  394.         if (poly[q].verts == 3)    /* we have reduced it to a triangle */
  395.         {
  396.             poly_to_face(q, 0);
  397.             del_poly(q, 0);
  398.         }
  399.     }
  400.  
  401.     /* change all instances of the second point into the first */
  402.     for (i1 = 0; i1 < faces; i1++)
  403.         for (vert = 0; vert < 3; vert++)
  404.             if (face[i1].p[vert] == p1)
  405.             {
  406.                 changed[found++] = i1;
  407.                 face[i1].p[vert] = p0;
  408.             }
  409.  
  410.     for (i1 = 0; i1 < polys; i1++)
  411.         for (vert = 0; vert < poly[i1].verts; vert++)
  412.             if (poly[i1].p[vert] == p1)
  413.             {
  414.                 changed[found++] = i1 | POLYFLAG;
  415.                 poly[i1].p[vert] = p0;
  416.             }
  417.     /* the join_p event is really only necessary if there were facets
  418.         referencing the eliminated point */
  419.     if (found) action_join_p(p0, p1, changed, found);
  420.  
  421.     del_point(p1, 1, 0);    /* kill quickly: assume the point is loose */
  422.                             /* but register the action */
  423.     move_point_to(p0, new.x, new.y, new.z);
  424. }
  425.  
  426.  
  427. void unfold()
  428. {
  429. }
  430.  
  431.  
  432. void stellate()
  433. {
  434.     int go = 1, event;
  435.     int id;
  436.     long data = 100, mag = 100;    /* magnitude of stellation */
  437.     int rel_to;
  438.     int add_p, add_f, del_f, del_q;
  439.     index po0;
  440.     long total_verts = 0;    /* total edges of all polygons */
  441.     int max_verts = 0;        /* the most verts on any polygon */
  442.     int verts;
  443.  
  444.     sys_window(35, 4, "Stellate All Facets");
  445.     sys_movecur(1,0);
  446.     sys_say_text("Magnitude:");
  447.     sys_get_long(data, 1);
  448.     sys_movecur(1,1);
  449.     sys_say_text("Stellate relative to the object's");
  450.     sys_movecur(1,2);
  451.     sys_boolean("Face Center", 2);
  452.     sys_say_text(" or ");
  453.     sys_boolean("Radius", 3);
  454.     sys_activate(1);
  455.  
  456.     while (go)
  457.     {
  458.         event = sys_read_event(&id, &data);
  459.         switch (event)
  460.         {
  461.         case EV_CANCEL:
  462.             sys_close_window();
  463.             return;
  464.             break;
  465.         case EV_CHECKINT:
  466.         case EV_HITRETURN:
  467.         case EV_HITBUTTON:
  468.             if (id == 1)
  469.             {
  470.                 if (data > 1000) data = 1000;
  471.                 if (data < -1000) data = -1000;
  472.                 mag = data;
  473.             }
  474.             else if (id == 2)
  475.             {
  476.                 rel_to = 0;
  477.                 go = 0;
  478.             }
  479.             else if (id == 3)
  480.             {
  481.                 rel_to = 1;
  482.                 go = 0;
  483.             }
  484.             break;
  485.         }
  486.     }
  487.     sys_close_window();
  488.  
  489.     /* Estimate how many actions the stellation will require. */
  490.     for (po0 = 0; po0 < polys; po0++)
  491.     {
  492.         verts = poly[po0].verts;
  493.         total_verts += verts;
  494.         if (max_verts < verts) max_verts = verts;
  495.     }
  496.     add_p = faces + polys;
  497.     add_f = (faces * 3);        /* for the faces */
  498.     add_f += total_verts;        /* for the polys */
  499.     del_f = faces;
  500.     del_q = polys;
  501.  
  502.     /* Make sure that this event won't overflow the undo buffer */
  503.     if (!enough_room(add_p, add_f, 0, 0, del_f, del_q, 0, max_verts))
  504.     {
  505.         /* this operation will overflow the undo buffer! */
  506.         if (!tell_user_overflow()) return;
  507.     }
  508.     begin_operation();
  509.     stellate0(mag, rel_to);
  510.     end_operation();
  511. }
  512.  
  513.  
  514. void stellate0(stellar_mag, rel_to)
  515. int stellar_mag;    /* magnitude of the stellation */
  516. int rel_to;            /* 0 = relative to face center, 1 = relative to radius */
  517. {
  518.     uindex
  519.         p0, p1, i, j,
  520.         old_points, old_faces, old_polys,
  521.         edges;
  522.     index np;            /* new point (the one we've just created) */
  523. #if INTEGER
  524.     long vx, vy, vz;
  525. #else
  526.     double vx, vy, vz;
  527. #endif
  528.     double cx, cy, cz, radius;    /* center coordnates for polyhedron */
  529.     double new_radius, scale_factor;
  530.     index new_faces;
  531.     char text[80];
  532.  
  533.     if (!faces && !polys) return;    /* must have something to stellate */
  534.  
  535.     begin_operation();
  536.  
  537.     /* estimate how many new faces will be generated */
  538.     new_faces = (faces * 3);
  539.     for (i = 0; i < polys; i++)
  540.         new_faces += poly[i].verts;
  541.  
  542.     if (faces + new_faces >= MAX_FACES)    /* need to make room for the new faces */
  543.     {
  544.         if (more_faces(faces + new_faces + 100))
  545.         {
  546.             sprintf(text, "increased face space to %d", MAX_FACES);
  547.             screen_say(text);
  548.         }
  549.         else
  550.         {
  551.             sprintf(text, "not enough memory for %d new faces", new_faces);
  552.             screen_say(text);
  553.             return;                /* failure */
  554.         }
  555.     }
  556.     old_points = points;    /* After we've created the stellated points */
  557.     old_faces = faces;        /* and faces, we'll remove the old faces. */
  558.     old_polys = polys;        /* And polygons. (but NOT the old points) */
  559.  
  560.     /* assume it's a polyhedron that we're operating on */
  561.     find_center(&cx, &cy, &cz);
  562.     find_radius(cx, cy, cz, &radius);
  563.  
  564.     /**** First we create the new points from the old faces ****/
  565.     for (i = 0; i < old_faces; i++)
  566.     {
  567.         vx = vy = vz = 0;
  568.         for (j = 0; j < 3; j++)
  569.         {
  570.             p0 = face[i].p[j];
  571.             vx += (point[p0].x - cx);
  572.             vy += (point[p0].y - cy);
  573.             vz += (point[p0].z - cz);
  574.         }
  575.         /* project point at face center out to stellar length */
  576.         vx /= 3;
  577.         vy /= 3;
  578.         vz /= 3;
  579.         new_radius = sqrt((double)(vx*vx + vy*vy + vz*vz));
  580.         if (rel_to)
  581.             scale_factor = (new_radius + stellar_mag) / new_radius;
  582.         else
  583.             scale_factor = (radius + stellar_mag) / new_radius;
  584.         np = add_point((coord)(cx + (double)vx * scale_factor),
  585.                       (coord)(cy + (double)vy * scale_factor),
  586.                       (coord)(cz + (double)vz * scale_factor));
  587.  
  588.         /* Add stellation */
  589.         add_face(face[i].p[0], face[i].p[1], np, colors.newface, 0);
  590.         add_face(face[i].p[1], face[i].p[2], np, colors.newface, 0);
  591.         add_face(face[i].p[2], face[i].p[0], np, colors.newface, 0);
  592.     }
  593.  
  594.     /* and from the old polygons */
  595.     for (i = 0; i < old_polys; i++)
  596.     {
  597.         vx = vy = vz = 0;
  598.         edges = poly[i].verts;
  599.         for (j = 0; j < edges; j++)
  600.         {
  601.             p0 = poly[i].p[j];
  602.             vx += (point[p0].x - cx);
  603.             vy += (point[p0].y - cy);
  604.             vz += (point[p0].z - cz);
  605.         }
  606.         vx /= edges;
  607.         vy /= edges;
  608.         vz /= edges;
  609.         new_radius = sqrt((double)(vx*vx + vy*vy + vz*vz));
  610.         if (rel_to)
  611.             scale_factor = (new_radius + stellar_mag) / new_radius;
  612.         else
  613.             scale_factor = (radius + stellar_mag) / new_radius;
  614.         np = add_point((coord)(cx + (double)vx * scale_factor),
  615.                       (coord)(cy + (double)vy * scale_factor),
  616.                       (coord)(cz + (double)vz * scale_factor));
  617.         /* Add stellation */
  618.         for (j = 0; j < edges; j++)
  619.         {
  620.             p0 = poly[i].p[j];
  621.             p1 = poly[i].p[(j+1)%edges];
  622.             add_face(p0, p1, np, colors.newface, 1);
  623.         }
  624.     }
  625.  
  626.     /*** Now we must destroy the original points, faces, and polys ***/
  627.     for (i = 0; i < faces-old_faces; i++) face[i] = face[old_faces+i];
  628.  
  629.     /* make sure we release the memory held by the original polys */
  630.     for (i = 0; i < old_polys; i++) kill_poly(i);
  631.     for (i = 0; i < polys-old_polys; i++) poly[i] = poly[old_polys+i];
  632.  
  633.     faces -= old_faces;
  634.     polys -= old_polys;
  635.  
  636.     end_operation();
  637. }
  638.  
  639.  
  640. void find_dual()
  641. {
  642.     uindex
  643.         p0, i, j, k,
  644.         af, adj_f[MAX_EDGES],    /* number and indices of the adjacent faces */
  645.         ap, adj_p[MAX_EDGES],    /* number and indices of the adjacent polys */
  646.         np, new_p[MAX_EDGES],
  647.         old_points, old_faces, old_polys,
  648.         edges;
  649.     index used_f[MAX_EDGES], used_p[MAX_EDGES];
  650. #if INTEGER
  651.     long vx, vy, vz;
  652. #else
  653.     double vx, vy, vz;
  654. #endif
  655.     double cx, cy, cz, radius;    /* center coordnates for polyhedron */
  656.     double new_radius, scale_factor;
  657.     int flag;
  658. #define DF_POLY 1
  659. #define DF_FACE 2
  660.     index previous;
  661.  
  662.     if (!faces && !polys) return;    /* must have something to dualize */
  663.     if (!dual_ok()) return;
  664.  
  665.     begin_operation();
  666.  
  667.     old_points = points;    /* After we've created the dual's points */
  668.     old_faces = faces;        /* and faces, we'll remove the old ones. */
  669.     old_polys = polys;        /* And polygons. */
  670.  
  671.     if (flags.assume_poly)    /* assume it's a polyhedron that we're operating on */
  672.     {
  673.         find_center(&cx, &cy, &cz);
  674.         find_radius(cx, cy, cz, &radius);
  675.     }
  676.  
  677.     /**** First we create the new points from the old faces ****/
  678.     for (i = 0; i < old_faces; i++)
  679.     {
  680.         vx = vy = vz = 0;
  681.         for (j = 0; j < 3; j++)
  682.         {
  683.             p0 = face[i].p[j];
  684.             if (flags.assume_poly)
  685.             {
  686.                 vx += (point[p0].x - cx);
  687.                 vy += (point[p0].y - cy);
  688.                 vz += (point[p0].z - cz);
  689.             }
  690.             else
  691.             {
  692.                 vx += point[p0].x;
  693.                 vy += point[p0].y;
  694.                 vz += point[p0].z;
  695.             }
  696.         }
  697.         if (flags.assume_poly)    /* project point at face center out to radius length */
  698.         {
  699.             new_radius = sqrt((double)(vx*vx + vy*vy + vz*vz));
  700.             scale_factor = radius / new_radius;
  701.             add_point((coord)(cx + (double)vx * scale_factor),
  702.                       (coord)(cy + (double)vy * scale_factor),
  703.                       (coord)(cz + (double)vz * scale_factor));
  704.         }
  705.         else
  706.             add_point(vx/3, vy/3, vz/3);    /* add a point at the face's center */
  707.     }
  708.  
  709.     /* and from the old polygons */
  710.     for (i = 0; i < old_polys; i++)
  711.     {
  712.         vx = vy = vz = 0;
  713.         edges = poly[i].verts;
  714.         for (j = 0; j < edges; j++)
  715.         {
  716.             p0 = poly[i].p[j];
  717.             if (flags.assume_poly)
  718.             {
  719.                 vx += (point[p0].x - cx);
  720.                 vy += (point[p0].y - cy);
  721.                 vz += (point[p0].z - cz);
  722.             }
  723.             else
  724.             {
  725.                 vx += point[p0].x;
  726.                 vy += point[p0].y;
  727.                 vz += point[p0].z;
  728.             }
  729.         }
  730.         if (flags.assume_poly)    /* project point at face center out to radius length */
  731.         {
  732.             new_radius = sqrt((double)(vx*vx + vy*vy + vz*vz));
  733.             scale_factor = radius / new_radius;
  734.             add_point((coord)(cx + (double)vx * scale_factor),
  735.                       (coord)(cy + (double)vy * scale_factor),
  736.                       (coord)(cz + (double)vz * scale_factor));
  737.         }
  738.         else add_point(vx/edges, vy/edges, vz/edges);    /* add a point at the poly's center */
  739.     }
  740.  
  741.     /* then for each point, we find the surrounding faces */
  742.     /* and make a face out of their corresponding points */
  743.  
  744.     for (i = 0; i < old_points; i++)
  745.     {
  746.         if (flags.debug) printf("Point %d: ", i);
  747.         af = ap = 0;
  748.  
  749.         for (j = 0; j < old_faces; j++)
  750.             if (face[j].p[0] == i || face[j].p[1] == i || face[j].p[2] == i)
  751.                 adj_f[af++] = j;
  752.  
  753.         for (j = 0; j < old_polys; j++)
  754.             for (k = 0; k < poly[j].verts; k++)
  755.                 if (poly[j].p[k] == i) adj_p[ap++] = j;
  756.  
  757.         if (flags.debug)
  758.         {
  759.             if (flags.debug) printf("%d adjacent faces:", af);
  760.             if (af) for (j = 0; j < af; j++) printf(" %d", adj_f[j]);
  761.             printf("\n");
  762.             printf("         %d adjacent polys:", ap);
  763.             if (ap) for (j = 0; j < ap; j++) printf(" %d", adj_p[j]);
  764.             printf("\n");
  765.         }
  766.  
  767.         if (af+ap == 3)        /* three points are a simple face */
  768.         {
  769.             if (flags.debug) printf(" %d %d  adding face:", af, ap);
  770.             np = 0;
  771.             for (j = 0; j < af; j++)
  772.                 new_p[np++] = adj_f[j];
  773.             for (j = 0; j < ap; j++)
  774.                 new_p[np++] = old_faces + adj_p[j];
  775.             if (flags.debug)
  776.             {
  777.                 printf("   ->");
  778.                 for (j = 0; j < 3; j++) printf(" %d", new_p[j]);
  779.                 printf("\n");
  780.             }
  781.             add_face(new_p[0], new_p[1], new_p[2], colors.newface, 1);
  782.         }
  783.         else if (af+ap > 3)
  784.         {
  785.             if (flags.debug) printf(" %d %d  adding POLYGON:", af, ap);
  786.             for (j = 0; j < af; j++) used_f[j] = 0;
  787.             for (j = 0; j < ap; j++) used_p[j] = 0;
  788.             allocate_poly(af+ap, colors.newface);
  789.  
  790.             /*** At this point we must arrange the points in the correct
  791.                 order to produce a correct polygon. ***/
  792.             /* We pick one arbitrary starting face, then advance around
  793.                 the point by finding adjacent faces/polys that we haven't
  794.                 used before. */
  795.             np = 0;
  796.             if (af)    /* pick starting point at 0 */
  797.             {
  798.                 previous = poly[polys].p[np++] = adj_f[0];
  799.                 used_f[0] = 1;
  800.                 flag = DF_FACE;
  801.             }
  802.             else
  803.             {
  804.                 previous = adj_p[0];
  805.                 poly[polys].p[np++] = old_faces + adj_p[0];
  806.                 used_p[0] = 1;
  807.                 flag = DF_POLY;
  808.             }
  809.             np = 1;
  810.             while (np < af+ap)
  811.             {
  812.                 for (k = 0; k < af; k++)    /* search faces */
  813.                 {
  814.                     if (used_f[k]) continue;    /* skip already-used faces */
  815.                     if (adjacent_xx(previous, adj_f[k], (flag == DF_POLY), 0))
  816.                     {
  817.                         previous = poly[polys].p[np++] = adj_f[k];
  818.                         used_f[k] = 1;
  819.                         flag = DF_FACE;
  820.                     }
  821.                 }
  822.                 for (k = 0; k < ap; k++)    /* search polys */
  823.                 {
  824.                     if (used_p[k]) continue;    /* skip already-used polys */
  825.                     if (adjacent_xx(previous, adj_p[k], (flag == DF_POLY), 1))
  826.                     {
  827.                         poly[polys].p[np++] = old_faces + adj_p[k];
  828.                         previous = adj_p[k];
  829.                         used_p[k] = 1;
  830.                         flag = DF_POLY;
  831.                     }
  832.                 }
  833.             }
  834.             finish_poly(0);
  835.             if (flags.debug)
  836.             {
  837.                 printf("   ->");
  838.                 for (j = 0; j < af+ap; j++) printf(" %d", poly[polys-1].p[j]);
  839.                 printf("\n");
  840.             }
  841.         }
  842.     }
  843.  
  844.     if (flags.debug)
  845.     {
  846.         printf("points %d, faces %d, polys %d\n", points, faces, polys);
  847.         printf("starting destruction:\n");
  848.     }
  849.  
  850.     /*** Now we must destroy the original points, faces, and polys ***/
  851.  
  852.     for (i = 0; i < points-old_points; i++)
  853.         point[i] = point[old_points+i];
  854.     for (i = 0; i < faces-old_faces; i++) face[i] = face[old_faces+i];
  855.  
  856.     /* make sure we release the memory held by the original polys */
  857.     for (i = 0; i < old_polys; i++) kill_poly(i);
  858.     for (i = 0; i < polys-old_polys; i++) poly[i] = poly[old_polys+i];
  859.  
  860.     points -= old_points;
  861.     faces -= old_faces;
  862.     polys -= old_polys;
  863.  
  864.     if (flags.debug)
  865.     {
  866.         printf("ending destruction:\n");
  867.         printf("points %d, faces %d, polys %d\n", points, faces, polys);
  868.     }
  869.     convert_points();
  870.     end_operation();
  871. }
  872.  
  873.  
  874. /* returns whether it is OK to perform a dualize operation */
  875.  
  876. int dual_ok()
  877. {
  878.     index p0, f0, q0, v0, surround;
  879.     index p, f, q, dp, df, dq;
  880.  
  881.     if (!flags.undo_active) return 1;    /* always OK if undo is off */
  882.     p = f = q = 0;
  883.  
  884.     /* Estimate how many faces and polys will need to be created */
  885.     for (p0 = 0; p0 < points; p0++)
  886.     {
  887.         surround = 0;
  888.         for (f0 = 0; f0 < faces; f0++)
  889.             if (face[f0].p[0] == p0 ||face[f0].p[2] == p0 ||face[f0].p[1] == p0)
  890.                 surround ++;
  891.         for (q0 = 0; q0 < polys; q0++)
  892.             for (v0 = 0; v0 < poly[q0].verts; v0++)
  893.                 if (poly[q0].p[v0] == p0)
  894.                     surround ++;
  895.         if (surround == 3) f++;
  896.         if (surround > 3) q++;
  897.     }
  898.     p = faces + polys;    /* each facet becomes a point */
  899.     dp = points;
  900.     df = faces;
  901.     dq = polys;
  902.     /* Make sure that this event won't overflow the undo buffer */
  903.     if (!enough_room(p, f, q, dp, df, dq, 0, 0))
  904.     {
  905.         /* this operation will overflow the undo buffer! */
  906.         if (!tell_user_overflow()) return 0;
  907.     }
  908.     return 1;
  909. }
  910.  
  911.  
  912. /*
  913.     Compare a face to face, face to poly, poly to face, or poly to poly.
  914.     The two flag arguments indicate what type of face the first two arguments
  915.     are (flag = TRUE if they indicated argument is a poly)
  916. */
  917.  
  918. index adjacent_xx(qf0, qf1, poly_flag0, poly_flag1)
  919. uindex qf0, qf1;
  920. int poly_flag0, poly_flag1;
  921. {
  922.   if (poly_flag0)
  923.   {
  924.     if (poly_flag1)
  925.         return adjacent_pp(qf0, qf1);
  926.     else
  927.         return adjacent_fp(qf1, qf0);
  928.   }
  929.   else
  930.   {
  931.     if (poly_flag1)
  932.         return adjacent_fp(qf0, qf1);
  933.     else
  934.         return adjacent_ff(qf0, qf1);
  935.   }
  936. }
  937.  
  938.  
  939. /*
  940.     Compare two faces to see if they share an edge: returns 1 or -1
  941.     depending on the direction of the match, 0 if there is no shared
  942.     edge.
  943. */
  944.  
  945. index adjacent_ff(f0, f1)
  946. uindex f0, f1;
  947. {
  948.     uindex e, e2, p00, p01, p10, p11;
  949.     index *fpp = face[f1].p;
  950.  
  951.     for (e = 0; e < 3; e++)
  952.     {
  953.       p00 = face[f0].p[e];
  954.       p01 = face[f0].p[(e+1)%3];
  955.       for (e2 = 0; e2 < 3; e2++)
  956.       {
  957.         /* There are two ways that one edge can match another:
  958.             the point numbers can be identical or inverted.
  959.             Edge i has indices i, (i+1)%3 for i = 0,1,2.
  960.         */
  961.         p10 = fpp[e2];
  962.         p11 = fpp[(e2+1)%3];
  963.  
  964.         if (p00 == p10 && p01 == p11) return 1;
  965.         else if (p00 == p11 && p01 == p10) return -1;
  966.       }
  967.     }
  968.     return (index)0;
  969. }
  970.  
  971.  
  972. /*
  973.     Compare a face to a poly to see if they share any edge: returns 1 or -1
  974.     depending on the direction of the match, 0 if there is no shared
  975.     edge.
  976. */
  977.  
  978. index adjacent_fp(f0, q0)
  979. uindex f0, q0;
  980. {
  981.     uindex e, e2, p00, p01, p10, p11, verts;
  982.     index *fpp = face[f0].p;
  983.     index *qpp = poly[q0].p;
  984.  
  985.     verts = poly[q0].verts;
  986.  
  987.     for (e = 0; e < 3; e++)
  988.     {
  989.       p00 = fpp[e];
  990.       p01 = fpp[(e+1)%3];
  991.       for (e2 = 0; e2 < verts; e2++)
  992.       {
  993.         p10 = qpp[e2];
  994.         p11 = qpp[(e2+1)%verts];
  995.  
  996.         if (p00 == p10 && p01 == p11) return 1;
  997.         else if (p00 == p11 && p01 == p10) return -1;
  998.       }
  999.     }
  1000.     return (index)0;
  1001. }
  1002.  
  1003.  
  1004. /*
  1005.     Compare a poly to a poly to see if they share any edge: returns 1 or -1
  1006.     depending on the direction of the match, 0 if there is no shared
  1007.     edge.
  1008. */
  1009.  
  1010. index adjacent_pp(q0, q1)
  1011. uindex q0, q1;
  1012. {
  1013.     uindex e, e2, p00, p01, p10, p11, verts0, verts1;
  1014.     index *qp0 = poly[q0].p;
  1015.     index *qp1 = poly[q1].p;
  1016.  
  1017.     verts0 = poly[q0].verts;
  1018.     verts1 = poly[q1].verts;
  1019.  
  1020.     for (e = 0; e < verts0; e++)
  1021.     {
  1022.       p00 = qp0[e];
  1023.       p01 = qp0[(e+1)%verts0];
  1024.       for (e2 = 0; e2 < verts1; e2++)
  1025.       {
  1026.         p10 = qp1[e2];
  1027.         p11 = qp1[(e2+1)%verts1];
  1028.  
  1029.         if (p00 == p10 && p01 == p11) return 1;
  1030.         else if (p00 == p11 && p01 == p10) return -1;
  1031.       }
  1032.     }
  1033.     return (index)0;
  1034. }
  1035.  
  1036.  
  1037. /*
  1038.     The idea here is to match 3 points with the points
  1039.         of some face.  There are 3! == 6 ways (permutations)
  1040.         that the three point numbers can match the selected points.
  1041. */
  1042.  
  1043. index points_are_a_face(ps0, ps1, ps2)
  1044. uindex ps0, ps1, ps2;
  1045. {
  1046.     uindex f, p0, p1, p2;
  1047.  
  1048.     for (f = 0; f < faces; f++)        /* search all faces */
  1049.     {
  1050.         p0 = face[f].p[0];
  1051.         p1 = face[f].p[1];
  1052.         p2 = face[f].p[2];
  1053.  
  1054.         if ((p0 == ps0 && p1 == ps1 && p2 == ps2) ||
  1055.             (p0 == ps0 && p1 == ps2 && p2 == ps1) ||
  1056.             (p0 == ps1 && p1 == ps0 && p2 == ps2) ||
  1057.             (p0 == ps1 && p1 == ps2 && p2 == ps0) ||
  1058.             (p0 == ps2 && p1 == ps0 && p2 == ps1) ||
  1059.             (p0 == ps2 && p1 == ps1 && p2 == ps0))
  1060.         {
  1061.             return (index)f;
  1062.         }
  1063.     }
  1064.     return (index)-1;
  1065. }
  1066.  
  1067.  
  1068. /*    Same as the above function, only it works with two points,
  1069.     returning a face that the two points (edge) share (if there is one).
  1070.     This function could be used to see if two points are "connected",
  1071.     or to find a face adjacent to an edge.  For this second usage,
  1072.     we don't want to find the original face, so we pass its number
  1073.     so that we can avoid it.
  1074. */
  1075.  
  1076. index face_next_to_edge(ps0, ps1, avoid_f)
  1077. uindex ps0, ps1;
  1078. index avoid_f;
  1079. {
  1080.     uindex f, p0, p1, p2;
  1081.  
  1082.     for (f = 0; f < faces; f++)        /* search all faces */
  1083.     {
  1084.         p0 = face[f].p[0];
  1085.         p1 = face[f].p[1];
  1086.         p2 = face[f].p[2];
  1087.  
  1088.         if ((p0 == ps0 && p1 == ps1) ||
  1089.             (p1 == ps0 && p0 == ps1) ||
  1090.             (p0 == ps0 && p2 == ps1) ||
  1091.             (p2 == ps0 && p0 == ps1) ||
  1092.             (p1 == ps0 && p2 == ps1) ||
  1093.             (p2 == ps0 && p1 == ps1))
  1094.         {
  1095.             if (f != avoid_f) return (index)f;
  1096.         }
  1097.     }
  1098.     return (index)-1;
  1099. }
  1100.  
  1101.  
  1102. /* check if a point is a member of any face */
  1103.  
  1104. index point_is_on_a_face(ps0)
  1105. uindex ps0;
  1106. {
  1107.     uindex f;
  1108.  
  1109.     for (f = 0; f < faces; f++)        /* search all faces */
  1110.         if (face[f].p[0] == ps0 || face[f].p[1] == ps0 || face[f].p[2] == ps0)
  1111.             return (index)f;
  1112.     return (index)-1;
  1113. }
  1114.  
  1115.  
  1116. /* check if a point is a member of any poly */
  1117.  
  1118. index point_is_on_a_poly(ps0)
  1119. uindex ps0;
  1120. {
  1121.     uindex po, v;
  1122.  
  1123.     for (po = 0; po < polys; po++)        /* search all faces */
  1124.         for (v = 0; v < poly[po].verts; v++)
  1125.             if (poly[po].p[v] == ps0)
  1126.                 return (index)po;
  1127.     return (index)-1;
  1128. }
  1129.  
  1130.  
  1131. index points_are_on_a_poly(array, verts)
  1132. uindex *array, verts;
  1133. {
  1134.     uindex po, pverts, test;
  1135.     register uindex i, j;
  1136.  
  1137.     if (!polys) return (index)-1;
  1138.  
  1139.     for (po = 0; po < polys; po++)
  1140.     {
  1141.         pverts = poly[po].verts;
  1142.         if (pverts < verts) continue;    /* skip simpler polys */
  1143.  
  1144.         for (i = 0; i < pverts; i++)
  1145.         {
  1146.             /* test forwards */
  1147.             test = 1;
  1148.             for (j = 0; j < verts; j++)
  1149.                 if (array[j] != poly[po].p[(i+j) % pverts])
  1150.                     { test = 0; break; }
  1151.             if (test) return (index)po;
  1152.  
  1153.             /* test backwards */
  1154.             test = 1;
  1155.             for (j = 0; j < verts; j++)
  1156.                 if (array[verts-j-1] != poly[po].p[(i+j) % pverts])
  1157.                     { test = 0; break; }
  1158.             if (test) return (index)po;
  1159.         }
  1160.     }
  1161.     return -1;
  1162. }
  1163.  
  1164.  
  1165. /*
  1166.     Like face_next_to_edge, except it works with polys.
  1167.     You can optionally pass a poly index for it to ignore.
  1168.     Returns -1 on failure.
  1169. */
  1170.  
  1171. index poly_next_to_edge(ps0, ps1, avoid_p)
  1172. uindex ps0, ps1;
  1173. index avoid_p;
  1174. {
  1175.     uindex p, p0, p1, v, verts;
  1176.  
  1177.     for (p = 0; p < polys; p++)        /* search all polys */
  1178.     {
  1179.         verts = poly[p].verts;
  1180.         p0 = poly[p].p[verts-1];
  1181.         for (v = 0; v < verts; v++)
  1182.         {
  1183.             p1 = poly[p].p[v];
  1184.     
  1185.             if ((p0 == ps0 && p1 == ps1) ||
  1186.                 (p1 == ps0 && p0 == ps1))
  1187.             {
  1188.                 if (p != avoid_p) return (index)p;
  1189.             }
  1190.             p0 = p1;
  1191.         }
  1192.     }
  1193.     return (index)-1;
  1194. }
  1195.  
  1196.  
  1197. void zoom(buttons)
  1198. int buttons;
  1199. {
  1200.     register coord oldgx = gx, oldgy = gy, oldgz = gz;
  1201.  
  1202.     if (buttons & 1)
  1203.         SCALE /= 0.9;
  1204.      else
  1205.         SCALE *= 0.9;
  1206.  
  1207.     convert_to_xyz(mx, my);
  1208.  
  1209.     offset.x += oldgx - gx;
  1210.     offset.y += oldgy - gy;
  1211.     offset.z += oldgz - gz;
  1212.     convert_points();
  1213.     refresh_all();
  1214. }
  1215.  
  1216.  
  1217. void set_rot_axis(x, y, z)
  1218. coord x, y, z;
  1219. {
  1220.     axis.x = x;
  1221.     axis.y = y;
  1222.     axis.z = z;
  1223.  
  1224.     mode = M_ROTP;
  1225.     draw_bars();
  1226.     rot_angle = 0.0;
  1227.     draw_rot();    /* Redraw angle */
  1228. }
  1229.  
  1230.  
  1231. void rotate()
  1232. {
  1233.     register index i1;
  1234.     double  co = cos(rot_angle),
  1235.             si = sin(rot_angle);
  1236.     int move_p;
  1237.  
  1238.     if (flags.rotate_all)
  1239.         move_p = points;
  1240.     else
  1241.         move_p = selected;
  1242.  
  1243.     if (!enough_room(0, 0, 0, 0, 0, 0, move_p, 0))
  1244.     {
  1245.         /* this operation will overflow the undo buffer! */
  1246.         if (!tell_user_overflow()) return;
  1247.     }
  1248.  
  1249.     begin_operation();
  1250.     if (flags.rotate_all)
  1251.     {
  1252.         for (i1 = 0; i1 < points; i1++)
  1253.           rotate_point(i1, co, si);
  1254.     }
  1255.     else
  1256.     {
  1257.         for (i1 = 0; i1 < selected; i1++)
  1258.           rotate_point(select_p[i1], co, si);
  1259.     }
  1260.     end_operation();
  1261.     mode = M_ROTA;
  1262.     flags.copy_made = 0;
  1263.     refresh_all();
  1264. }
  1265.  
  1266.  
  1267. void rotate_point(p, co, si)
  1268. index p;    /* the point to rotate */
  1269. double co, si;    /* the cosine and sine of the angle to rotate */
  1270. {
  1271.     coord dx, dy, dz;
  1272.  
  1273.     dx = point[p].x - axis.x;
  1274.     dy = point[p].y - axis.y;
  1275.     dz = point[p].z - axis.z;
  1276.  
  1277.     switch (dmode)
  1278.     {
  1279.         case DM_XY:
  1280.             move_point_to(p, axis.x + (coord)(co*dx - si*dy),
  1281.                              axis.y + (coord)(si*dx + co*dy), point[p].z);
  1282.             break;
  1283.         case DM_XZ:
  1284.             move_point_to(p, axis.x + (coord)(co*dx - si*dz), point[p].y,
  1285.                              axis.z + (coord)(si*dx + co*dz));
  1286.             break;
  1287.         case DM_ZY:
  1288.             move_point_to(p, point[p].x, axis.y + (coord)(si*dz + co*dy),
  1289.                              axis.z + (coord)(co*dz - si*dy));
  1290.             break;
  1291.         case DM_3D:
  1292.             break;
  1293.     }
  1294.     convert_point(p);
  1295. }
  1296.  
  1297.  
  1298. void find_center(cx, cy, cz)
  1299. double *cx, *cy, *cz;
  1300. {
  1301.     long sum_x, sum_y, sum_z;
  1302.     register unsigned int i;
  1303.  
  1304.     *cx = *cy = *cz = 0;
  1305.  
  1306.     if (!points) return;
  1307.  
  1308.     sum_x = sum_y = sum_z = 0;
  1309.     for (i = 0; i < points; i++)
  1310.     {
  1311.         sum_x += point[i].x;
  1312.         sum_y += point[i].y;
  1313.         sum_z += point[i].z;
  1314.     }
  1315.     *cx = (double)sum_x / points;
  1316.     *cy = (double)sum_y / points;
  1317.     *cz = (double)sum_z / points;
  1318. }
  1319.  
  1320.  
  1321. void find_radius(cx, cy, cz, radius)
  1322. double cx, cy, cz, *radius;
  1323. {
  1324.     register unsigned int i;
  1325.     coord dx, dy, dz;
  1326.     double dist = 0.0;
  1327.  
  1328.     for (i = 0; i < points; i++)
  1329.     {
  1330.         dx = point[i].x - cx;
  1331.         dy = point[i].y - cy;
  1332.         dz = point[i].z - cz;
  1333.         dist += sqrt((double)(dx*dx + dy*dy + dz*dz));
  1334.     }
  1335.     *radius = dist / (double)points;
  1336. }
  1337.  
  1338.  
  1339. /*
  1340.     This integer sqrt function is about *15* times faster than
  1341.     the standard double-precision math function under lattice.
  1342.     It was the result of a thread on comp.graphics a while ago.
  1343.     I've tested the precise accuracy of it's results up to 600000.
  1344.      I suppose if i was a real CS god i could PROVE that this algo
  1345.     always works.
  1346. */
  1347.  
  1348. unsigned long isqrt(v)
  1349. unsigned long v;
  1350. {
  1351.     register long t = 1L<<30, r = 0, s;
  1352.  
  1353. #define STEP(k) s = t + r; r >>= 1; if (s <= v) { v -= s; r |= t;}
  1354.  
  1355.     STEP(15);    t >>= 2;
  1356.     STEP(14);    t >>= 2;
  1357.     STEP(13);    t >>= 2;
  1358.     STEP(12);    t >>= 2;
  1359.     STEP(11);    t >>= 2;
  1360.     STEP(10);    t >>= 2;
  1361.     STEP(9);    t >>= 2;
  1362.     STEP(8);    t >>= 2;
  1363.     STEP(7);    t >>= 2;
  1364.     STEP(6);    t >>= 2;
  1365.     STEP(5);    t >>= 2;
  1366.     STEP(4);    t >>= 2;
  1367.     STEP(3);    t >>= 2;
  1368.     STEP(2);    t >>= 2;
  1369.     STEP(1);    t >>= 2;
  1370.     STEP(0);
  1371.  
  1372.     return (ULONG)r;
  1373. }
  1374.  
  1375.  
  1376. /* return fibonacci element (sum of natural numbers up to n) */
  1377.  
  1378. fibo(n)
  1379. {
  1380.     int sum = 0;
  1381.  
  1382.     while (n)
  1383.     {
  1384.         sum += n;
  1385.         n--;
  1386.     }
  1387.     return sum;
  1388. }
  1389.  
  1390.  
  1391. void set_clockwisdom()
  1392. {
  1393.     index f, q;
  1394.  
  1395.     for (f = 0; f < faces; f++)
  1396.     {
  1397.         if (determine_clockwisdom(face[f].p[0], face[f].p[1], face[f].p[2]))
  1398.         {
  1399.             change_face_clockwisdom(f);
  1400.         }
  1401.     }
  1402.     for (q = 0; q < polys; q++)
  1403.     {
  1404.         if (determine_clockwisdom(poly[q].p[0], poly[q].p[1], poly[q].p[2]))
  1405.         {
  1406.             change_face_clockwisdom(f);
  1407.         }
  1408.     }
  1409. }
  1410.  
  1411.  
  1412. int determine_clockwisdom(p0, p1, p2)
  1413. index p0, p1, p2;
  1414. {
  1415.     Point3D center;
  1416.     Vector3D v0, v1, v2, normal;
  1417.     coord dot;
  1418.  
  1419.     center.x = zero;
  1420.     center.y = zero;
  1421.     center.z = zero;
  1422.  
  1423.     v0.x = point[p0].x - center.x;
  1424.     v0.y = point[p0].y - center.y;
  1425.     v0.z = point[p0].z - center.z;
  1426.  
  1427.     v1.x = point[p1].x - center.x;
  1428.     v1.y = point[p1].y - center.y;
  1429.     v1.z = point[p1].z - center.z;
  1430.  
  1431.     v2.x = point[p2].x - center.x;
  1432.     v2.y = point[p2].y - center.y;
  1433.     v2.z = point[p2].z - center.z;
  1434.  
  1435.     /* now we find the normal by finding the cross product v0 X v1 */
  1436.     normal.x = v0.y * v1.z - v0.z * v1.y;
  1437.     normal.y = v0.z * v1.x - v0.x * v1.z;
  1438.     normal.z = v0.x * v1.y - v0.y * v1.x;
  1439.     /* note that there is no need to normalize the normal */
  1440.  
  1441.     /* we now have a definition of the plane through {center, p0, p1} */
  1442.     /* the dot product of v2 with the plane's normal gives the distance
  1443.         to the plane, of which we are only interested in the sign */
  1444.     dot = v2.x * normal.x + v2.y * normal.y + v2.z * normal.z;
  1445.     return (dot > zero);
  1446. }
  1447.  
  1448.  
  1449. void change_face_clockwisdom(f)
  1450. index f;
  1451. {
  1452.     index tmp;
  1453.     tmp = face[f].p[1];
  1454.     face[f].p[1] = face[f].p[2];
  1455.     face[f].p[2] = tmp;
  1456. }
  1457.  
  1458.  
  1459. void change_poly_clockwisdom(q)
  1460. index q;
  1461. {
  1462.     index tmp;
  1463.     index pi;    /* point index */
  1464.     int verts = poly[q].verts;
  1465.  
  1466.     for (pi = 1; pi < (verts+1)/2; pi++)
  1467.     {
  1468.         tmp = poly[q].p[pi];
  1469.         poly[q].p[pi] = poly[q].p[verts - pi];
  1470.         poly[q].p[verts - pi] = tmp;
  1471.     }
  1472. }
  1473.  
  1474.